#!/usr/bin/python2.4

# -*- coding: utf-8 -*-
#
#
# Copyright 2007 Google Inc. All Rights Reserved.

"""Unittest for objson module"""

__author__ = 'jimxu@gmail.com (Yongjian Xu)'


import os
import sys
sys.path.append('../')
from cStringIO import StringIO
import unittest
import objson
import objutils

class OBJsonTest(unittest.TestCase):

  def inithelper(self):
    self.json_feed = \
        r'''
        {"feed": {"category": [{"term":
        "http://schemas.gmail.com/g/2005#event", "scheme":
        "http://schemas.gmail.com/g/2005#kind"}], "updated": {"$t":
        "2007-04-16T19:11:33.000Z"}, "xmlns$gd":
        "http://schemas.gmail.com/g/2005", "subtitle": {"$t": "The calendar
        contains information about upcoming developer conferences at which
        Google will be speaking, along with other developer-related events.",
        "type": "text"}, "generator": {"$t": "Google Calendar", "version":
        "1.0", "uri": "http://www.gmail.com/calendar"}, "author": [{"name":
        {"$t": "Google Developer Calendar"}, "email": {"$t":
        "developer-calendar@gmail.com"}}], "xmlns$gCal":
        "http://schemas.gmail.com/gCal/2005", "title": {"$t": "Dev Events",
        "type": "text"}, "openSearch$startIndex": {"$t": "1"},
        "gCal$timezone": {"value": "America/Los_Angeles"}, "xmlns":
        "http://www.w3.org/2005/Atom", "link": [{"href":
        "http://www.gmail.com/calendar/feeds/developer-calendar%40gmail.com/public/full",
        "type": "application/atom+xml", "rel":
        "http://schemas.gmail.com/g/2005#feed"}, {"href":
        "http://www.gmail.com/calendar/feeds/developer-calendar%40gmail.com/public/full?alt=json&max-results=25",
        "type": "application/atom+xml", "rel": "self"}, {"href":
        "http://www.gmail.com/calendar/feeds/developer-calendar%40gmail.com/public/full?alt=json&start-index=26&max-results=25",
        "type": "application/atom+xml", "rel": "next"}],
        "xmlns$openSearch": "http://a9.com/-/spec/opensearchrss/1.0/",
        "openSearch$itemsPerPage": {"$t": "25"}, "entry": [{"category":
        [{"term": "http://schemas.gmail.com/g/2005#event", "scheme":
        "http://schemas.gmail.com/g/2005#kind"}], "gd$where":
        [{"valueString": "Paris, France"}], "updated": {"$t":
        "2007-03-12T23:05:23.000Z"}, "gd$comments": {"gd$feedLink":
        {"href":
        "http://www.gmail.com/calendar/feeds/developer-calendar%40gmail.com/public/full/dms62bpr8u1fs5vkpbb9bh854k/comments"}},
        "title": {"$t": "XTech 2007", "type": "text"}, "author":
        [{"name": {"$t": "Google Developer Calendar"}, "email":
        {"$t": "developer-calendar@gmail.com"}}], "gd$transparency":
        {"value":
        "http://schemas.gmail.com/g/2005#event.transparent"},
        "gd$eventStatus": {"value":
        "http://schemas.gmail.com/g/2005#event.confirmed"},
        "content": {"$t": "Jeff Scudder: Google Base, a mashups
        database for the REST of us\n\nFrank Mantek: Google Data
        API", "type": "text"}, "gCal$sendEventNotifications":
        {"value": "true"}, "link": [{"href":
        "http://www.gmail.com/calendar/event?eid=ZG1zNjJicHI4dTFmczV2a3BiYjliaDg1NGsgZGV2ZWxvcGVyLWNhbGVuZGFyQGdvb2dsZS5jb20",
        "type": "text/html", "rel": "alternate", "title":
        "alternate"}, {"href":
        "http://www.gmail.com/calendar/feeds/developer-calendar%40gmail.com/public/full/dms62bpr8u1fs5vkpbb9bh854k",
        "type": "application/atom+xml", "rel": "self"}],
        "published": {"$t": "2007-03-12T23:05:23.000Z"},
        "gd$when": [{"endTime": "2007-05-19", "gd$reminder":
        [{"minutes": "10"}], "startTime": "2007-05-15"}],
        "id": {"$t":
        "http://www.gmail.com/calendar/feeds/developer-calendar%40gmail.com/public/full/dms62bpr8u1fs5vkpbb9bh854k"}}],
        "id": {"$t":
        "http://www.gmail.com/calendar/feeds/developer-calendar%40gmail.com/public/full"}},
        "version": "1.0", "encoding": "UTF-8"}
        '''

  def setUp(self):
    self.inithelper()
    self.__io = StringIO(self.json_feed)

  def testPassInString(self):
    self.assert_(objson.OBJson(self.json_feed))

  def testPassInUnparseableString(self):
    self.assertRaises(objson.OBJsonRuntimeError, objson.OBJson, 'foobar')

  def testPassInFileObj(self):
    self.assert_(objson.OBJson(self.__io))

  def testPassInEmptyDict(self):
    src = {}
    result = {'_OBJson__parent': None}
    self.assertEqual(result, objson.OBJson(src).__dict__)

  def testIsOBJson(self):
    m = objson.OBJson(self.__io.read())
    self.assertTrue(objutils.IsOBJson(m))

  def testSanityCheck(self):
    self.assertRaises(objson.OBJsonTypeError, objutils.SanityCheck, 'foo')

  #def testinfo(self):
  #	m = objson.OBJson(self.__io.read())
  #	self.assert_(objson.info(m.feed))

  def testgen(self):
    m = objson.OBJson(self.__io.read())
    a = list(m.GetAttrs)
    b = [i[1] for i in objutils.gen(m)]
    a.sort()
    b.sort()
    self.assertNotEqual(a, b)
    if '_OBJson__parent' in a:
      a.pop(a.index('_OBJson__parent'))
    self.assertEqual(a, b)

  def testTraverseFail(self):
    #self.assertRaises(RuntimeError, objson.traverse, 123)
    self.assert_(objutils.traverse(123))

  def testSearchByTag(self):
    # There is an assumption that there is only one result returned.
    # Give a fixed json string, this is predictable.
    # TODO: should provide another test for testing the return 
    # multiple results.
    m = objson.OBJson(self.__io.read())
    tag = 'gd$feedLink'
    value = \
        r'''http://www.gmail.com/calendar/feeds/developer-calendar%40gmail.com/public/full/dms62bpr8u1fs5vkpbb9bh854k/comments'''
    v = objutils.SearchByTag(m, tag)
    self.assertEqual(value, v[2])

  def testSearchByVal(self):
    m = objson.OBJson(self.__io.read())
    value = r'''America/Los_Angeles'''
    v = objutils.SearchByVal(m, value)
    self.assertEqual(value, v[2])

  def testToJson(self):
    m = objson.OBJson(self.__io.read())
    self.assert_(objutils.ToJson(m))

  def testGetName(self):
    m = objson.OBJson(self.__io.read())
    name = 'feed'
    self.assertEqual(name, m.feed.GetName)

  def testNameSpace(self):
    m = objson.OBJson(self.__io.read())
    ns = 'xmlns$gCal'
    nsv = 'http://schemas.gmail.com/gCal/2005'
    nsdict = dict(objutils.NameSpace(m))
    self.assertTrue(nsdict.has_key(ns))
    self.assertEqual(nsv, nsdict[ns])

  def testReadParent(self):
    m = objson.OBJson(self.__io.read())
    self.assertEqual(m, m.feed.ParentObj)

  def testWriteParentLooping(self):
    m = objson.OBJson(self.__io.read())
    parent = m.feed
    self.assertRaises(objson.OBJsonRuntimeError,
        m._DoSetParent, parent)

  def testHasChildPlainText(self):
    m = objson.OBJson(self.__io.read())
    child = 'xmlns$gd'
    self.assertTrue(m.feed.HasChild(child))

  def testHasChildObj(self):
    m = objson.OBJson(self.__io.read())
    child = m.feed
    self.assertTrue(m.HasChild(child))

  def testHasChildList(self):
    m = objson.OBJson(self.__io.read())
    child = m.feed.category
    self.assertTrue(m.feed.HasChild(child))

  def testHasChildFail(self):
    m = objson.OBJson(self.__io.read())
    child = getattr(m.feed, 'xmlns$gd')
    self.assertFalse(m.HasChild(child))

  def testchildren(self):
    m = objson.OBJson(self.__io.read())
    self.assertEqual(m.feed, m.GetChildren()[0])

  def testAppendChild(self):
    m = objson.OBJson(self.__io.read())
    newid = m.feed.id.MakeClone()
    newid_addr = id(newid)
    m.feed.AppendChild('id', newid)
    self.assertEqual(newid_addr, id(m.feed.id[1]))

  def testInsertChild(self):
    m = objson.OBJson(self.__io.read())
    newid = m.feed.id.MakeClone()
    newid_addr = id(newid)
    m.feed.InsertChild('id', newid, m.feed.id)
    self.assertEqual(newid_addr, id(m.feed.id[0]))

  def testUpdateChild(self):
    m = objson.OBJson(self.__io.read())
    t = getattr(m.feed.id, '___t')
    id = m.feed.id.MakeClone()
    setattr(id, '___t', t.replace('%40', '@'))
    m.feed.UpdateChild('id', id)
    self.assertNotEqual(t, getattr(m.feed.id, '___t'))

  def testDeleteChild(self):
    m = objson.OBJson(self.__io.read())
    m.DeleteChild(m.feed)
    self.assertFalse('feed' in m.GetAttrs)

  def testclone(self):
    m = objson.OBJson(self.__io.read())
    self.assertNotEqual(m.feed, m.feed.MakeClone())

  def testCloneChildHasParentNone(self):
    m = objson.OBJson(self.__io.read())
    c = m.feed.MakeClone()
    self.assertEqual(None, c.ParentObj)

  def tearDown(self):
    self.__io.close()


def main():
  unittest.main()


if __name__ == '__main__':
  main()

# vim :set ts=2 sw=2 expandtab
# The End
